/*
 * FSWUniCEUB - 2008
 * 
 * Este arquivo é de propriedade da Fábrica de Software do UniCEUB
 * 
 * Para mais informações entre em contato com a coordenação do
 * curso de Ciência da Computação da instituição.
 */

package br.uniceub.fsw.indicadores.facade;

import br.uniceub.fsw.arquitetura.persistencia.transacao.Transacao;
import br.uniceub.fsw.arquitetura.servico.exception.NegocioException;
import br.uniceub.fsw.indicadores.bo.PlanoMedicaoBO;
import br.uniceub.fsw.indicadores.dao.PlanoMedicaoDAO;
import br.uniceub.fsw.indicadores.vo.PlanoMedicaoObjetivoVO;
import br.uniceub.fsw.indicadores.dao.PlanoMedicaoObjetivoDAO;
import br.uniceub.fsw.indicadores.vo.ObjetivoVO;
import br.uniceub.fsw.indicadores.dao.ObjetivoDAO;
import br.uniceub.fsw.indicadores.vo.PlanoMedicaoVO;
import br.uniceub.fsw.indicadores.vo.IndicadorVO;
import br.uniceub.fsw.indicadores.dao.IndicadorDAO;
import br.uniceub.fsw.util.TabelaHtml;
import java.util.ArrayList;
import java.util.List;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Facade da entidade PlanoMedicao.
 * 
 * @author Filipe Scafuto Vieira
 */
public class PlanoMedicaoFacade {
    
    /**
     * Mensagem de retorno do sistema.
     */
    private String message;

    /**
     * Value object do Plano de Medicao.
     */
    private PlanoMedicaoVO planoMedicao;
    
    /**
     * Value object do objetivo selecionado.
     */
    private ObjetivoVO objetivo;
    
    /**
     * Lista de Objetivos
     */    
    private List<List> objetivos;
    
    /**
     * Lista de Objetivos do Indicador
     */
    private List<PlanoMedicaoObjetivoVO> objetivosPlanoMedicao;
    
     /**
     * Lista de indicadores relacionados
     */
    private List<IndicadorVO> indicadores;
    
    /**
     * Lista de Planos de Medição não aprovados
     */
    private List<PlanoMedicaoVO> planosMedicao;
    
    /**
     * Construtor da classe.
     */
    public PlanoMedicaoFacade() {  

        this.objetivos = new ArrayList<List>();
        ObjetivoVO exemploObjetivo = new ObjetivoVO();
        exemploObjetivo.setStObjetivoAtivo("S");
        List<ObjetivoVO> objs = new ObjetivoDAO().consultarPorExemplo(exemploObjetivo);
        for(int i= 0; i < objs.size(); i++) {
            List<String> temp = new ArrayList<String>();
            temp.add(objs.get(i).getIdObjetivo().toString());
            temp.add(objs.get(i).getNoObjetivo().toString());
            temp.add("N");
            this.objetivos.add(temp);
        }  
        
        planosMedicao = new PlanoMedicaoDAO().consultarValidos(false);
    }
    
    /**
     * Getter da mensagem de retorno.
     * 
     * @return Mensagem de retorno.
     */
    public String getMessage() {
        String retorno = null;
        if(this.message == null || this.message.isEmpty()) {
            retorno = "&nbsp";
        } else {
            retorno = this.message;
        }
        return retorno;
    }
    
    /**
     * Retorna o plano de medicao
     * 
     * @return Objeto planoMedicao.
     */
    public PlanoMedicaoVO getPlanoMedicao() {
        return this.planoMedicao;
    }
    
     /**
     * Retorna os objetivos relacionados ao plano de medição
     * 
     * @return Lista de Objetivos.
     */
    public List<List> getObjetivos() {
        return this.objetivos;
    }
    
     /**
     * Retorna os indicadores relacionados ao plano de medição
     * 
     * @return Lista de Indicadores.
     */
    public List<IndicadorVO> getIndicadores() {
        return this.indicadores;
    }
    
     /**
     * Retorna os Objetivos.
     * 
     * @return Lista de Objetivos.
     */
    public List<PlanoMedicaoObjetivoVO> getObjetivosPlanosMedicao() {
        return this.objetivosPlanoMedicao;
    }
    
    /**
     * Retorna o objetivo selecionado.
     * 
     * @return Objetivo.
     */
    public ObjetivoVO getObjetivo() {
        return this.objetivo;
    }
    
    /**
     * Retorna os planos de medição
     * 
     * @return Lista de Planos de Medição.
     */
    public List<PlanoMedicaoVO> getPlanosMedicao() {
        return this.planosMedicao;
    }
    
    /**
     * Responsável por executar a operação selecionada pelo usuário.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void operacao(HttpServletRequest req, HttpServletResponse resp) {
        String oper = req.getParameter("operacao");

        if(oper != null)
        {
            if (oper.equals("consultar")) {
                this.consultar(req, resp);
            }
            if (oper.equals("incluir")) {
                this.incluir(req, resp);
            }
            if (oper.equals("alterar")) {
                this.alterar(req, resp);
            }
            if (oper.equals("excluir")) {
                this.excluir(req, resp);
            }
            if (oper.equals("confirmar")) {
                this.confirmar(req, resp);
            }
            if (oper.equals("aprovar")) {
                this.aprovar(req, resp);
            }
            if (oper.equals("confirmarAprovacao")) {
                this.confirmarAprovacao(req, resp);
            }
        }
        if(req.getParameter("idPlanoMedicao") != null && req.getParameter("idPlanoMedicao").length() > 0) {
            try {
                PlanoMedicaoVO teste = new PlanoMedicaoVO();
                teste.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));
                indicadores = new IndicadorDAO().consultarPorPlanoMedicao(teste);
            }
            catch (NumberFormatException e) {             
            }
        }
    }
    
    /**
     * Consultar um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void consultar(HttpServletRequest req, HttpServletResponse resp) {
        String idPlanoMedicaoTmp = req.getParameter("idPlanoMedicao");
        
        Integer idPlanoMedicao = null;
        
        if(idPlanoMedicaoTmp == null || idPlanoMedicaoTmp.equals("")) {
            return;
        } else {
            idPlanoMedicao = Integer.parseInt(idPlanoMedicaoTmp);
        }
        
        planoMedicao = new PlanoMedicaoDAO().consultarPorId(idPlanoMedicao);
        
        if(planoMedicao != null) {         
            PlanoMedicaoObjetivoVO exemplo = new PlanoMedicaoObjetivoVO();
            
            exemplo.setCdPlanoMedicao(planoMedicao.getIdPlanoMedicao());
            objetivosPlanoMedicao = new PlanoMedicaoObjetivoDAO().consultarPorExemplo(exemplo);
            for(int i = 0; i < objetivosPlanoMedicao.size(); i++) {
                for(int j = 0; j < objetivos.size(); j++) {
                    try {
                        if(objetivosPlanoMedicao.get(i).getCdObjetivo().equals(Integer.valueOf(objetivos.get(j).get(0).toString()))) 
                           objetivos.get(j).set(2, "S");
                    }
                    catch(NumberFormatException e) {}
                }
            }            
        }
    }
    
    /**
     * Incluir um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void incluir(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = "";
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
   
        planoMedicao = new PlanoMedicaoVO();
        planoMedicao.setNoPlanoMedicao(req.getParameter("noPlanoMedicao").trim());
        planoMedicao.setDsPlanoMedicao(req.getParameter("dsPlanoMedicao").trim());
        planoMedicao.setDtCriacao(new Date());
        try {
            if(!req.getParameter("dtValidade").trim().isEmpty()) 
                planoMedicao.setDtValidade(sdf.parse(req.getParameter("dtValidade").trim()));
        }       
        catch (ParseException e) {
            mensagem = mensagem + "Data de Validade não é uma data existente.<br />";
        }  
        planoMedicao.setStPlanoMedicaoAprovado("N"); 
        planoMedicao.setStPlanoMedicaoVigente("N"); 
        
        // Marcar objetivos
        String parameter = "";
        for(int i = 0; i < objetivos.size(); i++) {
            parameter = "objetivos_" + objetivos.get(i).get(0);
            if(req.getParameter(parameter) != null && req.getParameter(parameter).equals("1"))
                objetivos.get(i).set(2, "S");
        }        
        
        try {
            new PlanoMedicaoBO().validaPlanoMedicao(planoMedicao, true);
        }
        catch(NegocioException e) {
            mensagem = mensagem + e.getMessage().replace("\n","<br />");
        }
        catch(Exception e) {
            mensagem = mensagem + e.getMessage();
        }

        if(mensagem.equals("")) { 
            try {
                PlanoMedicaoObjetivoVO pmo = new PlanoMedicaoObjetivoVO();
                PlanoMedicaoObjetivoDAO pmoDAO = new PlanoMedicaoObjetivoDAO();                
                
                Transacao.iniciar();
                new PlanoMedicaoDAO().inserir(planoMedicao);
                for(int i = 0; i < objetivos.size(); i++) {
                    if(objetivos.get(i).get(2).equals("S")) {
                        pmo.setCdPlanoMedicao(planoMedicao.getIdPlanoMedicao());
                        pmo.setCdObjetivo(Integer.parseInt(objetivos.get(i).get(0).toString()));                        
                        pmoDAO.inserir(pmo);
                    }
                }                
                Transacao.efetivar();
                mensagem = "Plano de medição incluído com sucesso.";                
            } catch (Exception ex) {
                Transacao.desfazer();
                mensagem = "Problema na inclusão do plano de medição: " + ex.getMessage();
            }
        }
        
        this.message = mensagem;
    }

    /**
     * Alterar um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void alterar(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = "";
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        
        planoMedicao = new PlanoMedicaoVO();
        
        try {
            planoMedicao.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));
        }
        catch (NumberFormatException e) {
        }   
        planoMedicao.setNoPlanoMedicao(req.getParameter("noPlanoMedicao").trim());
        planoMedicao.setDsPlanoMedicao(req.getParameter("dsPlanoMedicao").trim());
        try {
            if(!req.getParameter("dtCriacao").trim().isEmpty()) 
                planoMedicao.setDtCriacao(sdf.parse(req.getParameter("dtCriacao").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de Criação não é uma data existente.<br />";
        }
        try {
            if(!req.getParameter("dtValidade").trim().isEmpty()) 
                planoMedicao.setDtValidade(sdf.parse(req.getParameter("dtValidade").trim()));
        }        
        catch (ParseException e) {
            mensagem = mensagem + "Data de Validade não é uma data existente.<br />";
        }
        planoMedicao.setStPlanoMedicaoAprovado(req.getParameter("stPlanoMedicaoAprovado").trim());
        planoMedicao.setStPlanoMedicaoVigente(req.getParameter("stPlanoMedicaoVigente").trim());
     
        // Marcar objetivos
        String parameter = "";
        for(int i = 0; i < objetivos.size(); i++) {
            parameter = "objetivos_" + objetivos.get(i).get(0);
            if(req.getParameter(parameter) != null && req.getParameter(parameter).equals("1"))
                objetivos.get(i).set(2, "S");
        }     
        
       try {
            new PlanoMedicaoBO().validaPlanoMedicao(planoMedicao, false);
        }
        catch(NegocioException e) {
            mensagem = mensagem + e.getMessage().replace("\n","<br />");
        }
        catch(Exception e) {
            mensagem = mensagem + e.getMessage();
        }
        
        if(mensagem.equals("")) {   
            PlanoMedicaoDAO daoPlanoMedicao = new PlanoMedicaoDAO();
            try {
                new PlanoMedicaoBO().validaAlteracao(planoMedicao);   

                Transacao.iniciar();
                
                PlanoMedicaoObjetivoVO pmo = new PlanoMedicaoObjetivoVO();
                PlanoMedicaoObjetivoDAO pmoDAO = new PlanoMedicaoObjetivoDAO();                
          
                pmo.setCdPlanoMedicao(planoMedicao.getIdPlanoMedicao());
                List<PlanoMedicaoObjetivoVO> lista = pmoDAO.consultarPorExemplo(pmo);
                
                if(lista != null && lista.size() > 0) 
                    for(int i = 0; i < lista.size(); i++)
                        pmoDAO.excluir(lista.get(i));                

                daoPlanoMedicao.alterar(planoMedicao);
                
                for(int i = 0; i < objetivos.size(); i++) 
                    if(objetivos.get(i).get(2).equals("S")) {
                        pmo.setCdPlanoMedicao(planoMedicao.getIdPlanoMedicao());
                        pmo.setCdObjetivo(Integer.parseInt(objetivos.get(i).get(0).toString()));
                        pmoDAO.inserir(pmo);
                    }                
                
                
                Transacao.efetivar();
                mensagem = "Plano de medição alterado com sucesso.";                         
            } catch (NegocioException ex) {     
                mensagem = ex.getMessage();
                            
            } catch (Exception ex) {
                Transacao.desfazer();
                mensagem = "Problema na alteração do plano de medição: " + ex.getMessage();
            }
        }
         
        this.message = mensagem;
    }

    /**
     * Excluir um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void excluir(HttpServletRequest req, HttpServletResponse resp) {        
        String mensagem = null;
                
        planoMedicao = new PlanoMedicaoVO();
        
        try {
            planoMedicao.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));
        }
        catch (NumberFormatException e) {
            mensagem = "ID do plano de medição inválido";
        }
        
        if(mensagem == null) {
            try {
                new PlanoMedicaoBO().validaExclusão(planoMedicao);
                Transacao.iniciar();
                new PlanoMedicaoDAO().excluir(planoMedicao);
                Transacao.efetivar();
                mensagem = "Plano de medição excluído com sucesso.";
            }            
            catch (NegocioException ex) {
                mensagem = "-Problema na exclusão do plano de medição: " + ex.getMessage();
            }
            catch (Exception ex) {
                mensagem = ".Problema na exclusão do plano de medição: " + ex.getMessage();
            }
        }
        
        this.planoMedicao = null;
        
        this.message = mensagem;
    }
    
    /**
     * Confirmar a exclusão do plano de medição.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void confirmar(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = null; 
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");

        planoMedicao = new PlanoMedicaoVO();
        
        try {
            planoMedicao.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));            
        }
        catch(NumberFormatException e) {
            planoMedicao = null;
            mensagem = "ID do plano de medição desconhecido";
        }
        
        if(planoMedicao != null) {
            try {
                new PlanoMedicaoBO().validaExclusão(planoMedicao);               
            }
            catch (NegocioException ex) {
                mensagem = ex.getMessage();
                planoMedicao = null;
            }
            catch (Exception ex) {
                mensagem = "+Problemas na exclusão do plano de medição: " + ex.getMessage();
                planoMedicao = null;
            }
            
            if(mensagem == null) {
                planoMedicao.setNoPlanoMedicao(req.getParameter("noPlanoMedicao"));
                planoMedicao.setDsPlanoMedicao(req.getParameter("dsPlanoMedicao"));
                try {
                    if(!req.getParameter("dtValidade").trim().isEmpty()) 
                        planoMedicao.setDtValidade(sdf.parse(req.getParameter("dtValidade").trim()));
                }        
                catch (ParseException e) {   
                }
            }
            
            this.message = mensagem;
        }
    }
    
    /**
     * Aprovar um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void aprovar(HttpServletRequest req, HttpServletResponse resp) {
        String mensagem = null; 
        PlanoMedicaoDAO dao = new PlanoMedicaoDAO();

        planoMedicao = new PlanoMedicaoVO();
        
        try {
            planoMedicao.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));     
            planoMedicao = dao.consultarPorId(planoMedicao.getIdPlanoMedicao());
        }
        catch(NumberFormatException e) {
            planoMedicao = null;
            mensagem = "ID do plano de medição desconhecido";
        }
        
        if(planoMedicao != null) {
            try {
                new PlanoMedicaoBO().aprovaPlanoMedicao(planoMedicao);     
                mensagem = "Plano de Medição \"" + planoMedicao.getNoPlanoMedicao() + "\" aprovado com sucesso!";
                planosMedicao = dao.consultarValidos(false);
            }
            catch (NegocioException ex) {
                mensagem = ex.getMessage();
                planoMedicao = null;
            }   
            catch (Exception ex) {
                mensagem = ex.getMessage();
            }
        }
        
        this.message = mensagem;
    }
    
    /**
     * Confirmar aprovação de um PlanoMedicao.
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     */
    public void confirmarAprovacao(HttpServletRequest req, HttpServletResponse resp) { 
        String mensagem = null;
                
        planoMedicao = new PlanoMedicaoVO();
        
        try {
            planoMedicao.setIdPlanoMedicao(Integer.parseInt(req.getParameter("idPlanoMedicao")));            
            planoMedicao = new PlanoMedicaoDAO().consultarPorId(Integer.parseInt(req.getParameter("idPlanoMedicao")));
            if(planoMedicao == null)
                mensagem = "Plano de Medição inválido.";
        }
        catch(NumberFormatException e) {
            planoMedicao = null;
            mensagem = "ID do plano de medição desconhecido";
        }
        
        this.message = mensagem;
    }
    
    /**
     * Retorna uma lista de Planos de Medicao a partir de parâmetros da tela
     * 
     * @param req Requisição web do tipo HTTP.
     * @param resp Resposta da requisição HTTP.
     * @return objeto tabela com as informações necessárias
     */
    public TabelaHtml consultarPlanosMedicao(HttpServletRequest req, HttpServletResponse resp) {
        String nome = req.getParameter("noPlanoMedicao");
        
        if(nome != null) {
            TabelaHtml tabela = new TabelaHtml();
            
            tabela.setCampoRetorno("idPlanoMedicao");
            
            tabela.adicionarTitulo("Id");
            tabela.adicionarTamanho(0);
            tabela.adicionarTipo("Integer");
            tabela.adicionarStatus(false);

            tabela.adicionarTitulo("Nome");
            tabela.adicionarTamanho(50);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);

            tabela.adicionarTitulo("Validade");
            tabela.adicionarTamanho(13);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);

            tabela.adicionarTitulo("Status");
            tabela.adicionarTamanho(17);
            tabela.adicionarTipo("String");
            tabela.adicionarStatus(true);

            tabela.gravarCampos();
            
            // Lista de planos de medição
            PlanoMedicaoVO exemplo = new PlanoMedicaoVO();
            if(!nome.isEmpty())
                exemplo.setNoPlanoMedicao(nome);
            List<PlanoMedicaoVO> planosMed = new PlanoMedicaoDAO().consultarPorExemplo(exemplo);
            
            // Adiciona os valores de cada plano de medição nas listas de ids e nomes
            for(int i = 0; i < planosMed.size(); i++) {
                tabela.adicionarRegistro(converterVoParaString(planosMed.get(i)));
            }

            return tabela;
        }
        
        return null;
    }
    
    /**
     * Transforma os campos de um VO em uma lista de Strings
     * 
     * @return lista de strings com os valores em ordem
     */
    public List<String> converterVoParaString(PlanoMedicaoVO planoMedicao) {
        List<String> valores = new ArrayList<String>();
        
        valores.add(planoMedicao.getIdPlanoMedicao().toString());
        valores.add(planoMedicao.getNoPlanoMedicao());
        valores.add(planoMedicao.getDtValidade().toString());
        if (planoMedicao.getStPlanoMedicaoAprovado().equals("N"))
            valores.add("Não aprovado");
        else
            valores.add("Aprovado");
        return valores;
    }
}